package ro.romanescu.utilities;

import java.net.URL;

import java.util.LinkedList;
import java.util.StringTokenizer;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import org.codehaus.stax2.XMLInputFactory2;
import org.codehaus.stax2.XMLStreamReader2;


public class STAXUtils {
  private static final Logger log = LogManager.getLogger( STAXUtils.class );

  public static void getXMLNodes( URL file, String path, NodeAdapter nodeEventListener ) throws XMLStreamException {
    LinkedList listPath = new LinkedList();
    StringTokenizer tok = new StringTokenizer( path, "/" );
    while( tok.hasMoreElements() ) {
      listPath.add( tok.nextElement().toString() );
    }
    log.info( "Opening XML file to process: " + file );
    log.info( "Looking for path: " + path );
    XMLInputFactory2 xmlif = null;
    xmlif = ( XMLInputFactory2 )XMLInputFactory.newInstance();
    xmlif.setProperty( XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE );
    xmlif.setProperty( XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE );
    xmlif.setProperty( XMLInputFactory.IS_COALESCING, Boolean.FALSE );
    xmlif.configureForSpeed();

    XMLStreamReader2 xmlr = xmlif.createXMLStreamReader( file );

    int evtType;
    String currentElement;
    while( xmlr.next() != XMLEvent.END_DOCUMENT ) {
      evtType = xmlr.getEventType();
      switch( evtType ) {
        case XMLEvent.START_ELEMENT:
          currentElement = xmlr.getName().toString();
          if( listPath.size() > 1 && currentElement.equals( listPath.getFirst() ) ) {
            listPath.removeFirst();
          }
          if( listPath.size() == 1 
              && currentElement.equals( listPath.getFirst() ) 
              && nodeEventListener != null ) {
            nodeEventListener.onNode( xmlr );
          }
          break;
      }
    }
  }
}
